package org.rbac.dao;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.metadata.ClassMetadata;
import org.hibernate.transform.Transformers;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author kingschan
 *         date:2013-10-08
 */
@SuppressWarnings("unchecked")
public class BaseDao {
    public Logger log = LoggerFactory.getLogger(BaseDao.class);
    private SessionFactory sessionfactory;

    public SessionFactory getSessionfactory() {
        return sessionfactory;
    }

    public void setSessionfactory(SessionFactory sessionfactory) {
        this.sessionfactory = sessionfactory;
        Map<String, ClassMetadata> map = sessionfactory.getAllClassMetadata();
        Iterator<String> keys = map.keySet().iterator();
        while (keys.hasNext()) {
            String key = keys.next();
            ClassMetadata cmd = map.get(key);
            log.info(String.format("%s 主键字段%s,主键类型%s", cmd.getEntityName(), cmd.getIdentifierPropertyName(),
                    cmd.getIdentifierType().getName()
            ));
        }
        log.info("注入sessionfactory");
    }

    public Session getSession() {
        Session session = null;
        try {
            session = sessionfactory.getCurrentSession();
            //log.info("只有在事务管理下，才能通过 getCurrentSession() 得到 session ，如果显示这个信息，则说明事务管理工作起作用了。");
        } catch (HibernateException ex) {
            session = sessionfactory.openSession();
            log.info("*************************************************************");
            log.info("*                                                           *");
            log.error("*  通过  openSession() 得到。事务管理没有起作用，需要检查配置。  *" + ex);
            log.info("*                                                           *");
            log.info("*************************************************************");
        }
        return session;
    }


    /**
     * 保存一个对象
     *
     * @param obj
     */
    public void save(Object obj) {
        Session s = getSession();
        s.save(obj);
    }

    /**
     * 保存多个对象
     *
     * @param lis
     */
    public void saveList(List<?> lis) {
        Session session = getSession();
        for (int a = 0; a < lis.size(); a++) {
            session.save(lis.get(a));
            if (a % 50 == 0) {
                session.flush();
                session.clear();
            }
        }
    }

    /**
     * 根据hql返回一个list  如果有参数刚hql用?来表示条件
     *
     * @param hql
     * @param args 从1开始赋值
     * @return
     */
    public List<?> queryForList(String hql, Object... args) {
        List<?> lis = null;
        Session s = getSession();
        Query q = s.createQuery(hql);
        if (null != args && args.length > 0) {
            for (int i = 0; i < args.length; i++) {
                q.setParameter(i, args[i]);
            }
        }
        lis = q.list();
        return lis;
    }

    /**
     * sql查询
     *
     * @param sql
     * @param args
     * @return
     */

    public List<Object[]> query(String sql, Object... args) {
        List<?> lis = null;
        Session s = getSession();
        Query q = s.createSQLQuery(sql);
        if (null != args && args.length > 0) {
            for (int i = 0; i < args.length; i++) {
                q.setParameter(i, args[i]);
            }
        }
        lis = q.list();
        return (List<Object[]>) lis;
    }

    /**
     * 根据hql查询返回一个map
     *
     * @param hql
     * @param map
     * @param keyname
     * @param valuename
     * @return
     */
    public Map<String, Object> query(String hql, Map<String, Object> map, String keyname, String valuename) {
        Query q = getSession().createQuery(hql);
        if (null != map) {
            Iterator<String> itera = map.keySet().iterator();
            while (itera.hasNext()) {
                String key = itera.next();
                Object value = map.get(key);
                if (value.getClass().getSimpleName().matches(".*(\\[\\])$")) {
                    Object[] array = (Object[]) value;
                    q.setParameterList(key, array);
                } else if (value instanceof List<?>) {
                    List<?> lis = (List<?>) value;
                    q.setParameterList(key, lis);
                } else {
                    q.setParameter(key, value);
                }
            }
        }
        List<Map<String, Object>> lis = q.list();
        Map<String, Object> fmap = new HashMap<String, Object>();
        if (null != lis && lis.size() > 0) {
            for (Map<String, Object> map2 : lis) {
                fmap.put(map2.get(keyname).toString(), map2.get(valuename));
            }
        }
        return fmap;
    }

    /**
     * 分页查询
     *
     * @param hql
     * @param pageindex
     * @param limit
     * @param args
     * @return
     */
    public List<?> Pagination(String hql, int pageindex, int limit, Object... args) {
        List<?> lis = null;
        Session s = getSession();
        Query q = s.createQuery(hql);
        if (null != args && args.length > 0) {
            for (int i = 0; i < args.length; i++) {
                q.setParameter(i, args[i]);
            }
        }
        q.setFirstResult((pageindex - 1) * limit);
        q.setMaxResults((pageindex - 1) * limit + limit);
        lis = q.list();

        return lis;
    }

    /**
     * 修改一个实体
     *
     * @param obj
     */
    public void update(Object obj) {
        getSession().update(obj);
//		getSession().flush();
    }

    /**
     * 删除一个实体
     *
     * @param obj
     */
    public void delete(Object obj) {
        getSession().delete(obj);
//		getSession().flush();
    }

    /**
     * 删除多个实体
     */
    public void deleteList(List<?> lis) {
        Session session = getSession();
        for (int a = 0; a < lis.size(); a++) {
            session.delete(lis.get(a));
            if (a % 10 == 0) {
                session.flush();
                session.clear();
            }
        }
    }

    /**
     * 根据主键返回一个实体
     *
     * @param clazz
     * @param id
     * @return
     */
    public Object get(Class<?> clazz, Object id) {
        return getSession().get(clazz, (Serializable) id);
    }

    /**
     * 执行HQL
     *
     * @param hql
     */
    public int executeHQL(String hql, Object... args) {
        Query q = getSession().createQuery(hql);
        if (null != args && args.length > 0) {
            for (int i = 0; i < args.length; i++) {
                q.setParameter(i, args[i]);
            }
        }
        return q.executeUpdate();
    }

    /**
     * 执行HQL
     *
     * @param hql
     * @param map
     * @return
     */
    public int executeHQL(String hql, Map<String, Object> map) {
        Query q = getSession().createQuery(hql);
        if (null != map) {
            Iterator<String> itera = map.keySet().iterator();
            while (itera.hasNext()) {
                String key = itera.next();
                Object value = map.get(key);
                if (value.getClass().getSimpleName().matches(".*(\\[\\])$")) {
                    Object[] array = (Object[]) value;
                    q.setParameterList(key, array);
                } else if (value instanceof List<?>) {
                    List<?> lis = (List<?>) value;
                    q.setParameterList(key, lis);
                } else {
                    q.setParameter(key, value);
                }
            }
        }
        return q.executeUpdate();
    }

    /**
     * 执行SQL
     *
     * @param sql
     * @param args
     * @return
     */
    public int executeSQL(String sql, Object... args) {
        Query q = getSession().createSQLQuery(sql);
        if (null != args && args.length > 0) {
            for (int i = 0; i < args.length; i++) {
                q.setParameter(i, args[i]);
            }
        }
        return q.executeUpdate();
    }

    /**
     * hql单一值查值
     *
     * @param hql
     * @param args
     * @return
     */
    public Object uniqueQueryByHql(String hql, Object... args) {
        Query q = getSession().createQuery(hql);
        if (null != args && args.length > 0) {
            for (int i = 0; i < args.length; i++) {
                q.setParameter(i, args[i]);
            }
        }
        return q.uniqueResult();
    }

    /***
     * sql 单一值查值
     *
     * @param sql
     * @param args
     * @return
     */
    public Object uniqueQueryBySql(String sql, Map<String, Object> params) {
        Query q = getSession().createSQLQuery(sql);
        if (null != params && !params.isEmpty()) {
            Iterator<String> itera = params.keySet().iterator();
            while (itera.hasNext()) {
                String key = itera.next();
                q.setParameter(key, params.get(key));

            }
        }
        return q.uniqueResult();
    }

    /***
     * sql 单一值查值
     *
     * @param sql
     * @param args
     * @return
     */
    public Object uniqueQueryBySql(String sql, Object... args) {
        Query q = getSession().createSQLQuery(sql);
        if (null != args && args.length > 0) {
            for (int i = 0; i < args.length; i++) {
                q.setParameter(i, args[i]);
            }
        }
        return q.uniqueResult();
    }

    /**
     * 本地命名查询返回List<Map>
     *
     * @return
     * @throws Exception
     */
    public List<?> getNameQuery(String key, Object... args) throws Exception {
        List<Map<String, Object>> lis = null;
        Session s = getSession();
        Query q = s.getNamedQuery(key);
        if (null != args && args.length > 0) {
            for (int i = 0; i < args.length; i++) {
                q.setParameter(i, args[i]);
            }
        }
        q.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        lis = q.list();
        return lis;
    }

    /**
     * 执行sql语句返回list【map【String,object】】
     *
     * @param sql
     * @param objects
     * @return
     */
    public List<?> executeSQLQuery(String sql, Object... objects) {
        Session s = getSession();
        Query q = s.createSQLQuery(sql);
        if (null != objects && objects.length > 0) {
            for (int i = 0; i < objects.length; i++) {
                q.setParameter(i, objects[i]);
            }
        }
        q.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        return q.list();
    }


}
